#ifndef __AS_STD_LIB__H__
#define __AS_STD_LIB__H__

#include "ASDataType.h"

/*useful functions*/
#define as_array_size(a) (sizeof(a)/sizeof(a[0]))

/*std lib functions*/
#if defined(AS_RUN_ON_MRE)
#define as_sprintf sprintf
#define as_strcat strcat
#define as_strncpy strncpy
#define as_strstr strstr
#elif defined(AS_RUN_ON_SKY)
#define as_sprintf mrc_sprintf
#define as_strcat mrc_strcat
#define as_strncpy mrc_strncpy
#define as_strstr mrc_strstr
#endif
ASVOID* as_memset(ASVOID *dst, ASINT ch, ASUINT size);
ASVOID* as_memcpy(ASVOID *dst, ASVOID *src, ASUINT count);
ASINT as_strlen(ASSTR str);
ASINT as_strcmp(const ASSTR s1, const ASSTR s2);
ASSTR as_strcpy(ASSTR dest, ASSTR src);
ASINT as_atoi(ASSTR str);

ASINT as_wstrlen(ASWSTR wstr);
ASVOID as_wstrcpy(ASWSTR dst_wstr, const ASWSTR src_wstr);
ASVOID as_wstrncpy(ASWSTR dst_wstr, const ASWSTR src_wstr, ASINT cnts);
ASVOID as_wstrcat(ASWSTR dst_wstr, ASWSTR cat_wstr);
ASINT as_wstrcmp(ASWSTR dst_wstr, ASWSTR src_wstr);

/*memory functions*/
ASVOID* _as_calloc(ASINT size);
ASVOID* as_malloc(ASINT size);
ASVOID* as_realloc(ASVOID* ptr, ASINT size);
ASVOID _as_free(ASVOID* ptr);

/*file functions*/
ASINT as_file_open(ASSTR gb_path, as_file_op_mode mode);
ASVOID as_file_read(ASINT fh, ASVOID* data_p, ASINT len, ASINT* read);
ASVOID as_file_write(ASINT fh, ASVOID* data_p, ASINT len, ASINT* write);
ASINT as_file_seek(ASINT fh, ASINT offset, as_file_seek_type seek_type);
ASVOID as_file_delete(ASSTR gb_path);
ASVOID as_file_rename(ASSTR dst_gb_path, ASSTR src_gb_path);
ASVOID as_file_close(ASINT fh);
as_ret as_filedir_create(ASSTR gb_path);
as_ret as_filedir_delete(ASSTR gb_path);
ASINT as_inter_file_get_filesize(ASSTR gb_name);
ASINT as_find_first(const ASSTR gb_str, ASSTR out_path, ASINT out_path_buf_len);
as_ret as_find_next(ASINT find_handle, ASSTR out_path, ASINT out_path_buf_len);
as_ret as_find_end(ASINT find_handle);
//out_buffer should be ASNULL,if success,function will use this ptr to alloc memory and save info
ASVOID as_inter_file_load_data(ASSTR gb_name, ASUINT8** out_buffer, ASINT* out_len);
ASVOID as_inter_file_load_data_patial(ASSTR gb_name, ASUINT8** out_buffer, ASINT* out_len,
                                      ASINT offset_from_begin, ASINT len_want_read);

/*chars set functions*/
ASWSTR as_ucs2_from_gb2312(ASSTR gb_str);
ASWSTR as_ufg_tmp(ASINT idx, ASSTR gbs);
ASWSTR as_ucs2_from_ascii(ASSTR astr);
ASSTR as_ascii_from_ucs2(ASWSTR ucs2_str);

ASINT as_ucs2_to_ascii(ASSTR dst, ASWSTR src);
ASINT as_ascii_to_ucs2(ASWSTR dst, ASSTR src);

/*time function*/
/*followings: month or day begin with 1.
 *week idx: 0~6(Sunday ~ Saturday)
 */
ASVOID as_get_time(as_time* time_p);
ASBOOL as_get_if_leap_year(ASUINT16 year);
ASUINT8 as_get_days_of_month(ASUINT16 year, ASUINT8 month);
ASUINT16 as_get_day_of_year(ASUINT16 year, ASUINT8 month, ASUINT8 day);
void as_set_days_of_year_to_time(as_time* time_p, ASUINT days);
ASUINT8 as_get_week(ASUINT16 year, ASUINT8 month, ASUINT8 day);
ASUINT8 as_get_week_of_year(ASUINT16 year, ASUINT8 month, ASUINT8 day);
ASBOOL as_get_if_same_week(as_time time1, as_time time2);
ASINT32 as_get_days(as_time time1, as_time time2);

/*useful algorithm*/
//typedef ASINT (*as_sort_comparer)(void* a,void* b);
//typedef ASVOID (*as_sort_exchanger)(void* a,ASINT i,ASINT j);
//ASVOID as_array_quick_sort(void* a,ASINT len,as_sort_comparer comparer,as_sort_exchanger exchanger);

//#define as_array_quick_sort SGLIB_ARRAY_QUICK_SORT
//#define as_array_binary_search SGLIB_ARRAY_BINARY_SEARCH

/*             QUICK - SORT   (level 0)          */
#define SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, elem_exchanger) {\
        ASINT   _i_, _j_, _p_, _stacki_, _start_, _end_;\
        /* can sort up to 2^64 elements */\
        ASINT   _startStack_[64]; \
        ASINT   _endStack_[64];\
        type  _tmp_;\
        _startStack_[0] = 0;\
        _endStack_[0] = (max);\
        _stacki_ = 1;\
        while (_stacki_ > 0) {\
            _stacki_ --;\
            _start_ = _startStack_[_stacki_];\
            _end_ = _endStack_[_stacki_];\
            while (_end_ - _start_ > 2) {\
                _p_ = _start_;\
                _i_ = _start_ + 1;\
                _j_ = _end_ - 1;\
                while (_i_<_j_) {\
                    for(; _i_<=_j_ && comparator(((a)[_i_]),((a)[_p_]))<=0; _i_++) ;\
                    if (_i_ > _j_) {\
                        /* all remaining elements lesseq than pivot */\
                        elem_exchanger(type, a, _j_, _p_);\
                        _i_ = _j_;\
                    } else {\
                        for(; _i_<=_j_ && comparator(((a)[_j_]),((a)[_p_]))>=0; _j_--) ;\
                        if (_i_ > _j_) {\
                            /* all remaining elements greater than pivot */\
                            elem_exchanger(type, a, _j_, _p_);\
                            _i_ = _j_;\
                        } else if (_i_ < _j_) {\
                            elem_exchanger(type, a, _i_, _j_);\
                            if (_i_+2 < _j_) {_i_++; _j_--;}\
                            else if (_i_+1 < _j_) _i_++;\
                        }\
                    }\
                }\
                /* O.K. i==j and pivot is on a[i] == a[j] */\
                /* handle recursive calls without recursion */\
                if (_i_-_start_ > 1 && _end_-_j_ > 1) {\
                    /* two recursive calls, use array-stack */\
                    if (_i_-_start_ < _end_-_j_-1) {\
                        _startStack_[_stacki_] = _j_+1;\
                        _endStack_[_stacki_] = _end_;\
                        _stacki_ ++;\
                        _end_ = _i_;\
                    } else {\
                        _startStack_[_stacki_] = _start_;\
                        _endStack_[_stacki_] = _i_;\
                        _stacki_ ++;\
                        _start_ = _j_+1;\
                    }\
                } else {\
                    if (_i_-_start_ > 1) {\
                        _end_ = _i_;\
                    } else {\
                        _start_ = _j_+1;\
                    }\
                }\
            }\
            if (_end_ - _start_ == 2) {\
                if (comparator(((a)[_start_]),((a)[_end_-1])) > 0) {\
                    elem_exchanger(type, a, _start_, _end_-1);\
                }\
            }\
        }\
    }

/*             BINARY SEARCH (level 0)          */

#define SGLIB_ARRAY_BINARY_SEARCH(type, a, start_index, end_index, key, comparator, found, result_index) {\
        ASINT _kk_, _cc_, _ii_, _jj_, _ff_;\
        _ii_ = (start_index); \
        _jj_ = (end_index);\
        _ff_ = 0;\
        while (_ii_ <= _jj_ && _ff_==0) {\
            _kk_ = (_jj_+_ii_)/2;\
            _cc_ = comparator(((a)[_kk_]), (key));\
            if (_cc_ == 0) {\
                (result_index) = _kk_;    \
                _ff_ = 1;\
            } else if (_cc_ < 0) {\
                _ii_ = _kk_+1;\
            } else {\
                _jj_ = _kk_-1;\
            }\
        }\
        if (_ff_ == 0) {\
            /* not found, but set its resulting place in the array */\
            (result_index) = _jj_+1;\
        }\
        (found) = _ff_;\
    }



#endif//__AS_STD_LIB__H__